import { EventEmitter } from "events";

import { Socket } from "./socket";
import { Operation } from "../../app";
import Extentsion from "../../lib/extension";
import { OsInfo } from "../../typing";

import * as os from "os";
import * as ip from "ip";

const osInfo = {
    cpu: os.cpus()[0].model,
    type: os.type(),
    ip: ip.address(),
    totalmem: os.totalmem(),
};

export default class WebServer extends Extentsion {

    private socket: Socket;
    private osStatus: OsInfo;

    constructor(serviceEvent: EventEmitter, operation: Operation) {
        super(serviceEvent, operation);

        const socketEvent = new EventEmitter();
        socketEvent.on("error", (error, socketId) => {
            this.socket.send({
                leval: "error",
                type: "showMessage",
                title: "错误",
                content: error.message,
            }, socketId);
        });

        // 登录
        socketEvent.on("login", async ({ username, password, token }, callback) => {
            const result = await this.operation.login(username, password, token);
            if (result.lastToken) {
                // 单点登录，通知之前的socket断开
                await this.socket.send({ type: "kick" }, result.lastToken);
            }
            callback(result);
        });

        // 退出
        socketEvent.on("logout", async ({ token }) => {
            await this.operation.logout(token);
            this.socket.send({
                title: "系统消息",
                type: "showMessage",
                content: "账号已退出！",
                leval: "success"
            }, token);
            this.socket.send({ type: "logout" }, token);
        });

        socketEvent.on("init", (_data, callback) => {
            callback({ osInfo, services: this.services });
        });

        // 启动服务
        socketEvent.on("start", async (data) => {
            try {
                await this.operation.startService(data);
            } catch (error) {
                socketEvent.emit("error", error, data.token);
            }
        });

        // 重启服务
        socketEvent.on("restart", async (data) => {
            try {
                await this.operation.restartService(data);
            } catch (error) {
                socketEvent.emit("error", error, data.token);
            }
        });

        // 停止服务
        socketEvent.on("stop", async (data) => {
            try {
                await this.operation.stopService(data);
            } catch (error) {
                socketEvent.emit("error", error, data.token);
            }
        });

        // 获取服务进程内存占用
        socketEvent.on("getMemory", async (data) => {
            try {
                await this.operation.getServiceMemory(data);
            } catch (error) {
                socketEvent.emit("error", error, data.token);
            }
        });

        // 获取consul节点tag，待删除解耦
        socketEvent.on("getConsulNodeTags", async (data, callback) => {
            try {
                data.args = [data.serviceName];
                data.serviceName = "consul";
                data.funcName = "getServicrTags";
                const tags = await this.operation.omnipotent(data);
                callback({ tags });
            } catch (error) {
                socketEvent.emit("error", error, data.token);
            }
        });

        // 更新配置文件
        socketEvent.on("updateConfig", async (data) => {
            try {
                await this.operation.updateConfig(data);
            } catch (error) {
                socketEvent.emit("error", error, data.token);
            }
        });

        // 获取当前系统状态
        socketEvent.on("getOsStatus", async (_message, callback) => {
            const timestamp = new Date().getTime();
            if (!this.osStatus || timestamp - this.osStatus.timestamp > 1000) {
                this.osStatus = await this.operation.osStatus();
            }
            callback(this.osStatus);
        });

        // 获取配置文件
        socketEvent.on("getConfig", (_message, callback) => {
            callback(this.operation.getConfig());
        });

        // 获取服务配置文件
        socketEvent.on("getServiceConfig", async (data, callback) => {
            try {
                data.funcName = "getConfig";
                const result = await this.operation.omnipotent(data);
                callback(result);
            } catch (error) {
                socketEvent.emit("error", error, data.token);
            }
        });

        // 更新服务配置文件
        socketEvent.on("updateServiceConfig", async (data) => {
            try {
                data.funcName = "updateConfig";
                data.args = [data.config];
                await this.operation.omnipotent(data);
            } catch (error) {
                socketEvent.emit("error", error, data.token);
            }
        });

        socketEvent.on("runServiceScript", async (data) => {
            const funcList: string[] = data.pipe.split(/ *\| */);
            if (funcList.length === 0) {
                return;
            }
            for (const func of funcList) {
                data.funcName = func;
                data.args = [await this.operation.omnipotent(data)];
            }
            this.socket.send({
                title: "执行脚本",
                type: "showMessage",
                content: data.args[0],
                leval: "success"
            }, data.token);
        });

        this.socket =  new Socket(socketEvent);
    }

    public register() {
        const send = (message: { [key: string]: any }) => {
            this.socket.send(message);
        }
        this.serviceEvent.on("fork", send);
        this.serviceEvent.on("exit", send);
        this.serviceEvent.on("running", send);
        this.serviceEvent.on("memory", send);
        this.serviceEvent.on("info", send);
        this.serviceEvent.on("updateConfig", () => {
            this.socket.send({type: "updateConfig" });
            this.socket.send({
                title: "配置文件",
                type: "showMessage",
                content: "配置文件已更新！",
                leval: "success"
            });
        });
        this.serviceEvent.on("updateServiceConfig", (serviceName) => {
            this.socket.send({
                serviceName,
                type: "updateServiceConfig"
            });
            this.socket.send({
                title: "配置文件",
                type: "showMessage",
                content: serviceName + "配置文件已更新！",
                leval: "success"
            });
        });
    }
}